/*
    This file is part of Raptor.

    Raptor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Raptor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Raptor.  If not, see <http://www.gnu.org/licenses/>.

 */

#include "rapidshare_com.h"

pluginHoster::pluginHoster()
{
    action = ACTION_NONE;
    step = 0;
    multipl = 1024;
    waitingId = -1;
    abort = false;
    cookie = "";
    lastSize = 0;

    apiFileId = 0;
    apiFilename = "";
    apiHostname = "";
    apiAuth = "";
    apiWait = 0;
    apiMd5 = "";

    waitTimer.setSingleShot(false);
    waitTimer.setInterval(1000);

    speedTimer.setSingleShot(false);
    speedTimer.setInterval(this->speedIntervall);

    loadCookie();

    this->_state = STATE_STOPPED;

    this->_info.allowOtherHostnames = false;
    this->_info.free.downloads = 0;
    this->_info.free.maxDownloads = 1;
    this->_info.free.maxConnections = 1;
    this->_info.premium.downloads = 0;
    this->_info.premium.maxDownloads = 0;
    this->_info.premium.maxConnections = 0;
    this->_info.host = "rapidshare.com";
    this->_info.name = "rapidshare.com";
    this->_info.reHost = QRegExp("^(.*\\.)?rapidshare\\.com$");
    this->_info.reLink = QRegExp("^(https?://)?([^\\s]*\\.)?rapidshare\\.com([^\\s]*)$");
    this->_info.mode = this->_mode;

    QSettings settings("raptor-loader", "Raptor");
    this->_info.maxDownloads = settings.value("hoster/rapidshare.com/maxDownloads", "0").toInt();

    connect(&http, SIGNAL(requestFinished(int, bool)), this, SLOT(slot_http_requestFinished(int, bool)));
    connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)), this, SLOT(slot_http_readyRead(const QHttpResponseHeader &)));
    connect(&http, SIGNAL(dataReadProgress(int, int)), this, SLOT(slot_http_dataReadProgress(int, int)));
    connect(&http, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(slot_http_sslErrors(const QList<QSslError> &)));

    connect(&speedTimer, SIGNAL(timeout()), this, SLOT(slot_speedTimer_timeout()));
    connect(&waitTimer, SIGNAL(timeout()), this, SLOT(slot_waitTimer_timeout()));
}

pluginHoster::~pluginHoster()
{
//    qDebug() << QString("~pluginHoster no. %1").arg(this->_id);
}

QObject* pluginHoster::clone()
{
    return new pluginHoster();
}

void pluginHoster::start()
{
    this->_progress = 0;
    this->_state = STATE_RUNNING;

    step = 0;
    waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());

    /* API

    QRegExp reFileInfo("^(?:.*)rapidshare.com/files/([\\d]*)/(.*)$");
    if(reFileInfo.indexIn(this->_url.toString()) != -1)
    {
        this->apiFileId = reFileInfo.cap(1).toULong();
        this->apiFilename = reFileInfo.cap(2);
    }

    if(this->apiFileId == 0)
    {
        step = 0;
        waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
    } else
    {
        switch(this->_mode)
        {
            case MODE_FREE:
            {
                cookie = "";
                QByteArray post = "sub=download_v1&fileid=" + QUrl::toPercentEncoding(QString("%1").arg(this->apiFileId)) + "&filename=" + QUrl::toPercentEncoding(this->apiFilename);
                QUrl url("http://api.rapidshare.com/cgi-bin/rsapi.cgi");

                step = 1;
                waitingId = request(url, "POST", post, QMap<QString, QString>());

                break;
            }

            default:
            {
                waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
                break;
            }
        }
    }
    */
}

void pluginHoster::stop()
{
    if(this->_state != STATE_STOPPED)
    {
        abort = true;
        http.abort();
    }
}

void pluginHoster::login(QString const& user, QString const& pass)
{
    /*
    http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=subroutine (finalpoints=points)
    https://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=subroutine (finalpoints=points*2 (this means using SSL doubles points!))

    subroutine=getaccountdetails_v1
    Description:	Returns key-pair values for the specific account. Warning: The order may change, and we will probably add or remove values in the future.
            You should make sure that your program does not stop working if new values appear or existing values disappear.
    Parameters:	login=ID or username
            password=password of the login
            withpublicid=1 (Optional. If given, the reply also contains publicid=STRING. You need this string to receive Rapids by other users. See FAQ for further information.)
            withcookie=1 (Optional. If given, the reply also contains cookie=STRING. You need this string only if you need to set a valid encryped cookie.)
    Reply fields:	1:key 2:value
    Reply format:	string=string or integer\n...
    Reply example:	accountid=$accountid (integer)
            servertime=$time (integer)
            addtime=$addtime (integer)
            username=$username (string)
            directstart=$directstart (integer)
            verified=$verified (integer)
            rsantihack=$rsantihack (integer)
            mirrors=$mirrors (string)
            jsconfig=$jsconfig (string)
            email=$email (string)
            curfiles=$curfiles (integer)
            curspace=$curspace (integer)
            kff=$kff (stands for keepfilesforever) (integer)
            autoextend=$autoextend (integer)
            autorefill=$autorefill (integer)
            tskb=$tskb (integer)
            rapids=$rapids (integer)
            billeduntil=$billeduntil (integer)
            happyhours=$happyhours (0 or 1)
            publicid=$publicid (string, optional. See 'withpublicid' above.)
            cookie=$cookie (string. optional. See 'withcookie' above.)
    */

    const bool useSSL = true;
    QUrl url;

    this->_mode = MODE_LOGIN;

    cookie = "";

    QByteArray post = "sub=getaccountdetails_v1&withcookie=1&login=" + QUrl::toPercentEncoding(user) + "&password=" + QUrl::toPercentEncoding(pass);

    if(useSSL)
        url = QUrl("https://api.rapidshare.com/cgi-bin/rsapi.cgi");
    else
        url = QUrl("http://api.rapidshare.com/cgi-bin/rsapi.cgi");

    QMap<QString, QString> headerData;

    //headerData.insert("Referer", "https://ssl.rapidshare.com/premiumzone.html");
    //headerData.insert("Content-Type", "application/x-www-form-urlencoded");

    waitingId = request(url, "POST", post, headerData);
}

void pluginHoster::getSize()
{
    this->_mode = MODE_GET_SIZE;

    cookie = "";

    waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
}

bool pluginHoster::setLink(QUrl const& url)
{
    if(url.host().indexOf(this->_info.reHost) == -1)
    {
        return false;
    } else
    {
        this->_url = url;

        if(this->_url.host() != "rapidshare.com")
        {
            this->_url.setHost("rapidshare.com");
        }

        return true;
    }
}

void pluginHoster::createConfigDialog(QPointer<QGridLayout> hosterLayout)
{
    applyButton = new QPushButton(tr("Apply"));

    authLabel = new QLabel(tr("Premium Account Login:"));
    authUser = new QLineEdit("");
    authPass = new QLineEdit("");
    authPass->setEchoMode(QLineEdit::Password);
    authLogin = new QPushButton(tr("Login and save login data"));
    authDelete = new QPushButton(tr("Delete login data"));

    maxDownloadsLabel = new QLabel(tr("Maximum simultaneous downloads:"));
    maxDownloadsSpinBox = new QSpinBox();

    connect(authLogin, SIGNAL(clicked()), this, SLOT(slot_authLoginButton_clicked()));
    connect(authDelete, SIGNAL(clicked()), this, SLOT(slot_authDeleteButton_clicked()));
    connect(applyButton, SIGNAL(clicked()), this, SLOT(slot_applyButton_clicked()));

    hosterLayout->addWidget(authLabel, 0, 0);
    hosterLayout->addWidget(authUser, 0, 1);
    hosterLayout->addWidget(authPass, 0, 2);
    hosterLayout->addWidget(authLogin, 0, 3);
    hosterLayout->addWidget(authDelete, 0, 4);

    hosterLayout->addWidget(maxDownloadsLabel, 1, 0);
    hosterLayout->addWidget(maxDownloadsSpinBox, 1, 1);

    hosterLayout->addWidget(applyButton, 2, 0, 1, 5, Qt::AlignRight);

    maxDownloadsSpinBox->setValue(this->info().maxDownloads);
}

void pluginHoster::deleteConfigDialog()
{
    this->disconnect();

    if(authLabel) delete authLabel;
    if(authUser) delete authUser;
    if(authPass) delete authPass;
    if(authLogin) delete authLogin;
    if(authDelete) delete authDelete;
    if(maxDownloadsLabel) delete maxDownloadsLabel;
    if(maxDownloadsSpinBox) delete maxDownloadsSpinBox;

    if(applyButton) delete applyButton;
    if(authDelete) delete authDelete;

    this->http.abort();
}

//private ->

int pluginHoster::request(QUrl const& url, QString const& method, QByteArray const& post, QMap<QString, QString> const& headerData, QIODevice *io)
{
    response = "";

    QHttpRequestHeader header(method, url.path());
    header.setValue("Host", url.host());

    QMap<QString, QString>::const_iterator it = headerData.constBegin();
    for(;it!=headerData.constEnd(); ++it)
    {
        header.setValue(it.key(), it.value());
    }

    if(this->cookie != "") header.setValue("Cookie", this->cookie);

    if(url.toString().left(5) == "https")
    {
        this->http.setHost(url.host(), QHttp::ConnectionModeHttps);
    } else
    {
        this->http.setHost(url.host());
    }

    if(io == 0)
    {
        return this->http.request(header, post);
    } else
    {
        speedTimer.start(this->speedIntervall);
        return this->http.request(header, post, io);
    }
}

void pluginHoster::loadCookie()
{
    QSettings settings("raptor-loader", "Raptor");

    //settings.beginGroup("hoster/rapidshare.com/settings");
    QString enc = settings.value("hoster/rapidshare.com/settings/enc", "").toString();
    //settings.endGroup();

    if(enc == "")
    {
        this->_mode = MODE_FREE;
        cookie = "";
    } else
    {
        this->_mode = MODE_PREMIUM;
        cookie = QString("enc=%1").arg(enc);

        this->_info.premium.maxDownloads = settings.value("hoster/rapidshare.com/maxDownloads", "0").toInt();
    }
}

QString pluginHoster::selectMirror(QStringList const& list)
{
    if(list.size() > 0)
    {
        return list.at(0);
    } else
    {
        return "";
    }
}

void pluginHoster::setError()
{
    this->_state = STATE_ERROR;
    emit statusMsg(this->_logId, this->_errorStr);

    //emit deleteMe(this->_id, true);
    switch(this->_mode)
    {
        case MODE_GET_SIZE:
            emit getSizeFinished(this->_id, true);
            break;

        case MODE_LOGIN:
            emit loginFinished(this->_id, true);
            break;

        case MODE_FREE:
            emit downloadFinished(this->_id, true);
            break;

        case MODE_PREMIUM:
            emit downloadFinished(this->_id, true);
            break;
    }
}

bool pluginHoster::extractResponse(QString const& field, QString & value)
{
    QRegExp re(field + "=([^\n]*)\n");

    if(re.indexIn(page) != -1)
    {
        value = re.cap(1).trimmed();

        return true;
    }

    return false;
}

void pluginHoster::doLogin()
{
    QString tmpCookie = "";

    if(extractResponse("cookie", tmpCookie))
    {
        QSettings settings("raptor-loader", "Raptor");
        settings.setValue("hoster/rapidshare.com/settings/enc", tmpCookie);

        emit loginFinished(this->_id, false);
    } else
    {
        setError();
    }

    /*if(this->http.lastResponse().hasKey("Set-Cookie"))
    {
        QString tmpString = this->http.lastResponse().value("Set-Cookie");

        QStringList tmpStringList = tmpString.split(";");

        for(int i=0; i<tmpStringList.size(); ++i)
        {
            QStringList item = tmpStringList.at(i).split("=");

            if(item.size() == 2)
            {
                if(item.at(0) == "enc")
                {
                    if(item.at(1).trimmed() != "")
                    {
                        QSettings settings("raptor-loader", "Raptor");

                        settings.setValue("hoster/rapidshare.com/settings/enc", item.at(1).trimmed());
                        emit loginFinished(this->_id, false);
                    }
                }
            }
        }

        emit loginFinished(this->_id, true);
    } else
    {
        setError();
    }*/
}

void pluginHoster::doGetSize()
{
    switch(step)
    {
        default:
        case 0:
        {            
            if(this->http.lastResponse().hasKey("Location"))
            {
                this->_url = QUrl(this->http.lastResponse().value("Location"));
            }

            QRegExp re("<script(?:[^>]*)>location=\"([^\"]*)\";</script>");

            if(re.indexIn(page) != -1)
            {
                QStringList strList = re.cap(1).split("|");
                this->_fileSize = strList.at(4).toUInt()*multipl;

                this->apiFileId = strList.at(2).toULong();
                this->apiFilename = strList.at(3).trimmed();

                emit changeName(this->_id, this->apiFilename);
                emit getSizeFinished(this->_id, false);
            } else
            {
                if(page.indexOf("ERROR") != -1)
                {
                    qDebug() << "ErRor:" << page;
                    this->_errorStr = page.split("\n").at(0);
                    setError();
                } else
                {
                    waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
                }
            }

            /*


            if(this->http.lastResponse().hasKey("Location"))
            {
                this->_url = QUrl(this->http.lastResponse().value("Location"));
                qDebug() << "found Location" << this->_url;
                
                //waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
                return;
            }

            if(page.indexOf(QRegExp("<!-- E#4 -->")) != -1)
            {
                this->_errorStr = tr("The file could not be found. Please check the download link.");
                setError();
            } else
            {
                QRegExp re("<form action=\"([^\"]*)\" method");
                QRegExp re2("<script(?:[^>]*)>location=\"([^\"]*)\";</script>");

                if(re.indexIn(page) != -1)
                {
                    QUrl tmpUrl(re.cap(1));

                    QRegExp re2(">\\| (\\d+) (.)B</font></p>");
                    if(re2.indexIn(page) != -1)
                    {
                        quint64 tmpSize = re2.cap(1).toUInt();

                        QStringList sizeNames = QStringList() << " " << "K" << "M" << "G" << "T" << "P";

                        for(int i=0; i<sizeNames.count(); ++i)
                        {
                            if(re2.cap(2) == sizeNames.at(i))
                            {
                                double tmpDbl = tmpSize;

                                for(int o=0; o<i; ++o)
                                    tmpDbl = tmpDbl * multipl;

                                this->_fileSize = tmpDbl;
                            }
                        }

                    } else
                    {
                        this->_fileSize = 100*multipl*multipl;
                    }
                    emit getSizeFinished(this->_id, false);
                } else if(re2.indexIn(page) != -1)
                {
                    QStringList strList = re2.cap(1).split("|");
                    this->_fileSize = strList.at(4).toUInt()*multipl;
                    emit getSizeFinished(this->_id, false);
                } else
                {
                    this->_errorStr = tr("Unknown error !!");
                    setError();
                }
            }*/

            break;
        }
    }
}

void pluginHoster::doPremium()
{
    switch(step)
    {
        default:
        case 0:
        {
            QRegExp reErrorX("<!-- E#(\\d+) -->([^<]*)<");
            if(reErrorX.indexIn(page) != -1)
            {
                this->_errorStr = reErrorX.cap(2);
                setError();
                return;
            } else
            {
                QRegExp reCookie("<input type=\"hidden\" name=\"dl\\.start\" value=\"PREMIUM\" />");
                if(reCookie.indexIn(page) != -1)
                {
                    this->_errorStr = tr("Wrong cookie, switching to free mode.");

                    emit changeMode(this->_id, MODE_FREE);

                    setError();
                    return;
                } else
                {
                    /*for(int i=0; i<this->http.lastResponse().keys().size(); ++i)
                    {
                        qDebug() << this->http.lastResponse().keys().at(i) << this->http.lastResponse().value(this->http.lastResponse().keys().at(i));
                    }*/

                    QRegExp re("<script(?:[^>]*)>location=\"([^\"]*)\";</script>");
                    bool linkFound = false;

                    if(this->http.lastResponse().hasKey("Location"))
                    {
                        this->_url = QUrl(this->http.lastResponse().value("Location"));
                        linkFound = true;
                    } else if(re.indexIn(page) != -1)
                    {
                        //waitingId = request(QUrl("http://www.rapdishare.com" + re.cap(1)), "GET", QByteArray(), QMap<QString, QString>());
                        //return;
                    }

                    if(linkFound)
                    {
                        if(!this->_downloadDir.exists(this->_folder)) this->_downloadDir.mkdir(this->_folder);

                        this->_downloadDir.cd(this->_folder);

                        while(this->_downloadDir.exists(this->_file))
                        {
                            emit statusMsg(this->_logId, tr("file exists, renaming."));
                            this->_file = "_" + this->_file;
                        }

                        this->_downloadFile = new QFile(this->_downloadDir.filePath(this->_file));
                        if(!this->_downloadFile->open(QIODevice::WriteOnly))
                        {
                            this->_errorStr = this->_downloadFile->errorString();//tr("Cant open file.");
                            setError();
                            return;
                        }

                        step = 1;
                        response = "";

                        this->_state = STATE_DOWNLOADING;

                        emit statusMsg(this->_logId, tr("Starting download."));

                        this->_progress = 0;
                        this->_downloadStart = QDateTime::currentDateTime();
                        this->_downloadEnd = this->_downloadStart;
                        this->_downloadEnd.addSecs(-1);

                        waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>(), this->_downloadFile);
                    } else
                    {
                        qDebug() << page;
                        this->_errorStr = tr("Location not found in header. Please set 'Direct downloads' to 'On'.");
                        setError();
                        return;
                    }
                }
            }
            break;
        }

        case 1:
        {
            speedTimer.stop();

            this->_downloadFile->close();
            this->_downloadEnd = QDateTime::currentDateTime();
            this->_state = STATE_FINISHED;

            int secs = this->_downloadStart.secsTo(this->_downloadEnd);

            if(secs > 0)
            {
                this->_speed = (double)this->_fileSize / secs;
            } else
            {
                this->_speed = this->_fileSize;
            }

            emit downloadFinished(this->_id, false);

            break;
        }
    }
}

bool pluginHoster::checkRsResponse()
{
    /*if(this->http.lastResponse().hasKey("Location"))
    {
        qDebug() << "Location" << this->http.lastResponse().value("Location");
        waitingId = request(QUrl(this->http.lastResponse().value("Location")), "GET", QByteArray(), QMap<QString, QString>());
        return true;
    }*/

    QRegExp reDlauth("^DL:([^,]*),([^,]*),([^,]*),([^,]*)$");
    QRegExp re("<script(?:[^>]*)>location=\"([^\"]*)\";</script>");

    if(re.indexIn(page) != -1)
    {
        QStringList strList = re.cap(1).split("|");
        this->_fileSize = strList.at(4).toUInt()*multipl;

        //waitingId = request(QUrl("http://www.rapidshare.com" + re.cap(1)), "GET", QByteArray(), QMap<QString, QString>());

        this->apiFileId = strList.at(2).toULong();
        this->apiFilename = strList.at(3);
    }

    if(reDlauth.indexIn(page) != -1)
    {
        this->apiHostname = reDlauth.cap(1);
        this->apiAuth = reDlauth.cap(2);
        this->apiWait = reDlauth.cap(3).toInt();
        this->apiMd5 = reDlauth.cap(4);

        this->_state = STATE_WAITING;
        emit statusMsg(this->_logId, tr("Waiting %1 seconds.").arg(this->apiWait));

        action = ACTION_API;

        this->_timeLeft = this->apiWait;
        wait = this->_timeLeft;

        waitTimer.start(1000);

        return true;
    } else if(page.indexOf("ERROR") != -1)
    {
        QRegExp reWaits("You need to wait (\\d*) seconds");
        QRegExp reFull("All free download slots are full");

        if(reWaits.indexIn(page) != -1)
        {
            this->_timeLeft = reWaits.cap(1).toInt();
            wait = this->_timeLeft;

            action = ACTION_START;
            waitTimer.start(1000);

            this->_state = STATE_WAITING;
            emit statusMsg(this->_logId, tr("You need to wait %1 seconds.").arg(wait));

            return true;
        } else if(reFull.indexIn(page) != -1)
        {
            this->_timeLeft = 30;
            wait = this->_timeLeft;

            action = ACTION_START;
            waitTimer.start(1000);

            this->_state = STATE_WAITING;
            emit statusMsg(this->_logId, tr("All free download slots are full. Please try again later."));

            return true;
        } else
        {
            qDebug() << "ErRor:" << page;
            this->_errorStr = page.split("\n").at(0);
            return false;
        }
    } else
    {
        this->_errorStr = tr("Unknown error !!");
        return false;
    }
}

void pluginHoster::doFree()
{
    switch(step)
    {
        default:
        case 0:
        {
            /*
            if(!checkRsResponse())
            {
                setError();
                return;
            }*/


            //http://rapidshare.com/overlay_confirmation.tpl?tcv=123


            /*
system["tips"]["tip_help_ssldownload"]   = "Using this option downloads are transmitted via a specially secured connection. <b>Attention:</b> As this option requires more server capacity <i>Secure downloads</i> will be billed with twice the amount of Rapids.";

function CDownloadPage()
{
  var self = this;
  //self.hOldTimer = null;
  self.iCounter = -1;
  //self.freedlTimer = null;
  self.freedlCounter = -1;
  if( !self.vars )self.vars = new Object();
  self.vars["freedlurl"]        = null;
  self.vars["dl_file_serverid"] = null;
  self.vars["dl_file_id"]       = null;
  self.vars["dl_file_name"]     = null;
  self.vars["dl_file_sizekb"]   = null;
  self.vars["dl_error"]         = null;
  self.vars["shorthost"]        = RSPage["CDownloadPage_shorthost"];
  self.vars["downloadid"]       = RSPage["CDownloadPage_downloadid"];
  self.szFreeDLLink = "";
  self.szPremDLLink = "";
  self.animationComplete = false;
  self.buttonComplete = false;
  self.iframe = null;
  self.init = function()
  {
    self.checkHash();

    $('url_headarea').innerHTML = self.getFileURL();
    $('jsurl_file-download-size').innerHTML = self.vars["dl_file_sizekb"];
    $('jsurl_file-download-head').innerHTML = self.getFileURL();

    $('freedldone_sizekb').innerHTML = self.vars["dl_file_sizekb"];
    $('freedldone_url').innerHTML = self.getFileURL();

    $('wait4freedl_sizekb').innerHTML = self.vars["dl_file_sizekb"];
    $('wait4freedl_url').innerHTML = self.getFileURL();

    //DL-Zeit berechnung
    //self.vars["dl_file_sizekb"]
    var dlspeed = 600;
    var freedlspeed = 75;
    var dltime = Math.ceil(self.vars["dl_file_sizekb"]/dlspeed);
    var freedltime = Math.ceil(self.vars["dl_file_sizekb"]/freedlspeed);

    if(dltime>60)dltime = ((dltime-(dltime%60))/60) + "." + (dltime%60) + " minutes";
    else dltime = dltime + " Seconds";
    if(freedltime>60)freedltime = ((freedltime-(freedltime%60))/60) + "." + (freedltime%60) + " minutes";
    else freedltime = freedltime + " Seconds";

    $('dltime').innerHTML = dltime;
    $('freedltime').innerHTML = freedltime;

    //self.iframe = document.createElement("iframe");
    //self.iframe.style.position="absolute";
    //self.iframe.style.width="100px";
    //self.iframe.style.left="-200px";
    //self.iframe.name= "hiddeniframe"+intval(Math.random()*1000000);
    //$('content').appendChild(self.iframe);

    $('sidebar-lounge').style.display="none";
    $('sidebar-gute-gruende').style.display="block";
    if($('js-sidebar-help'))$('js-sidebar-help').style.display="block";
    //self.vxPrepareDLLink();

    if($("js_ssldownload").checked || system["user"]["settings"]["onlyssldls"]=="1")
        var szProtokoll = "https";
    else
        var szProtokoll = "http";
    var h = location.hash.split("|");
    h = h.slice(0,5);
    h = h.join("|");
    var url = szProtokoll+"://rs"+self.vars["dl_file_serverid"]+".rapidshare.com/cgi-bin/rsapi.cgi?sub=download_v1&cookie="+system["user"]["settings"]["cookie"]+"&editparentlocation=1&fileid=" + encodeURI(self.vars["dl_file_id"]) + "&filename=" + encodeURI(self.vars["dl_file_name"])+"&bin=1&dlauth=0&wantpremdl=1"+h;

    try {document.domain = 'rapidshare.com';} catch(e) {debug(e)}
    $("js_prem_sslchoose").style.display="";
    $("js_prem_downloadbtn").innerHTML = szxTranslate('<iframe name="###target###" style="display:none;"></iframe><a id="js_prem_downloadlink" href="###url###" target="###target###" class="rapid-download_btn">High-Speed Download</a>',{"url":url, "target":"hiddeniframe"+intval(Math.random()*1000000)});
  }
  self.vxPrepareDLLink = function() {
    //  Prepare DownloadLinks
    if(system["user"]["settings"]["cookie"]) {
      apicall("https://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=download_v1&fileid=" + encodeURI(self.vars["dl_file_id"]) + "&filename=" + encodeURI(self.vars["dl_file_name"])+"&try=1&cookie="+system["user"]["settings"]["cookie"], function(obj)
      {
        var aResp = obj.responseText.split(":");
        var bPremDl = false;
        if( aResp[0]=="DL" ){
          var aDetails = aResp[1].split(",");
          var host = aDetails[0];
          var dlauth = aDetails[1];
          var countdown = aDetails[2];
          var h = location.hash.split("|");
          h = h.slice(0,5);
          h = h.join("|");
          if(host && dlauth && countdown && dlauth==0 && countdown==0){ //RapidPro active
            if($("js_ssldownload").checked || system["user"]["settings"]["onlyssldls"]=="1")
                var szProtokoll = "https";
            else
                var szProtokoll = "http";
            var url = szProtokoll+"://"+host+"/cgi-bin/rsapi.cgi?sub=download_v1&cookie="+system["user"]["settings"]["cookie"]+"&editparentlocation=1&fileid=" + encodeURI(self.vars["dl_file_id"]) + "&filename=" + encodeURI(self.vars["dl_file_name"])+"&bin=1&dlauth="+dlauth+h;

            $("js_prem_downloadlink").href=url;
            $("js_prem_sslchoose").style.display="";
            $("js_prem_downloadlink").target = self.iframe.name;
          } else {
            showerror("Internal error: "+obj.responseText);
          }
        } else {
          self.vxProcessError(obj.responseText);
        }
        $("js_prem_downloadlink").style.display="";
      });
    } else {
        $("js_prem_downloadlink").style.display="";
        $("js_prem_downloadlink").href="javascript:void( RSPage['CDownloadPage'].vxShowBuyLogin() );";
    }

  }
  self.vxChangeSSL = function() {
    var url = $("js_prem_downloadlink").href.substr($("js_prem_downloadlink").href.indexOf("://"));
    $("js_prem_downloadlink").href = ($('js_ssldownload').checked || system["user"]["settings"]["onlyssldls"]=="1")?("https"+url):("http"+url);
  }
  self.cbOnLogin = function() { // Aufruf wenn neu eingeloggt
    vxCloseOverlay();
    self.vxPrepareDLLink();
  }
  self.startFreeDl = function(){
    $('sidebar-lounge').style.display="none";
    $('sidebar-gute-gruende').style.display="block";
    if($('js-sidebar-help'))$('js-sidebar-help').style.display="block";

    apicall("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=download_v1&fileid=" + encodeURI(self.vars["dl_file_id"]) + "&filename=" + encodeURI(self.vars["dl_file_name"])+"&try=1", function(obj)
    {
        var aResp = obj.responseText.split(":");
        var bPremDl = false;
        if( aResp[0]=="DL" ){
          var aDetails = aResp[1].split(",");
          var host = aDetails[0];
          var dlauth = aDetails[1];
          var countdown = aDetails[2];

          var h = location.hash.split("|");
          h = h.slice(0,5);
          h = h.join("|");

          self.vars["freedlurl"] = "http://"+host+"/cgi-bin/rsapi.cgi?sub=download_v1&editparentlocation=0&bin=1&fileid=" + encodeURI(self.vars["dl_file_id"]) + "&filename=" + encodeURI(self.vars["dl_file_name"])+"&dlauth="+dlauth+h;

          self.iCounter = countdown;
          $('js_download-timer_counter').innerHTML = self.iCounter;
          $('js_download-timer_counterstart').innerHTML = self.iCounter;
          $('js_download-timer-box').style.display='none';
          $('js_download-timer-waitingbox').style.display='block';

          if (system["downloadtimer"]) clearInterval(system["downloadtimer"]);
          system["downloadtimer"] = setInterval("RSPage['CDownloadPage'].startFreeDlTimerRun()",1000);
          // IE-Fix (opt. DownloadButton):
          if($("js_downloadnowlink")) {
            $("js_downloadnowlink").href = self.vars["freedlurl"];
            //$("js_downloadnowlink").target = self.iframe.name;
          }

        } else {    //  Error
          self.vxProcessError(obj.responseText);
        }
    });
  }
  self.startFreeDlTimerRun=function(){
    if(self.iCounter==0){
      clearInterval(system["downloadtimer"]);
      $('downloadpage_wrapper').style.display='none';
      $('downloadpage_freedl_wrapper').style.display='block';

      $('sidebar-lounge').style.display="block";
      $('sidebar-gute-gruende').style.display="none";
      if($('js-sidebar-help'))$('js-sidebar-help').style.display="none";
      // normale Browser sofort starten // IE unterdrücken
//      if(window.innerWidth)
//        self.iframe.src=self.vars["freedlurl"];
    } else {
      self.iCounter--;
    }
    $('js_download-timer_counter').innerHTML = self.iCounter;
  }

  self.checkHash = function()
  {
    var params = ( system["params"] || location.hash.split("|") );
    //debug(params);
    self.vars["dl_file_serverid"] = params[1];
    self.vars["dl_file_id"]       = params[2];
    self.vars["dl_file_name"]     = params[3];
    self.vars["dl_file_sizekb"]   = params[4];

    self.vars["dl_error"] = params[5]||null;

    if(self.vars["dl_error"]){
      var h = location.hash.split("|");
      h = h.slice(0,5);
      h = h.join("|");
      system["oldHash"]=h; // prevent reload due of hashchange!
      location.hash=h;
      self.vxProcessError(self.vars["dl_error"]);
    }
  }
  self.vxShowBuyLogin = function() {
    RSPage["package"] = 1;
    load("overlay_downloadbuy.tpl", "", function(obj) {
        if($("overlay-box").style.display=="none") {
            $("js_overlay-box-content").innerHTML = trim(obj.responseText);
            RSPage["CPayment"].initPage();
            RSPage["CPayment"].vxSetLoginCallback(self.cbOnLogin);
            vxOpenOverlay();
        } else {
            vxResizeOverlay(function(){
              $("js_overlay-box-content").innerHTML = trim(obj.responseText);
              RSPage["CPayment"].initPage();
              RSPage["CPayment"].vxSetLoginCallback(self.cbOnLogin);
            });
        }
    });
  }
  self.vxProcessError = function(err) {
    if(startswith(err, "ERROR:")) err=err.substr(6);
    err=trim(err);
    var szError = "";
    / * durch RPro lösbare Probleme * /
    switch(err) {
      case "Premium download failed.": // Freeuser klickt premdownload an
      case "ERROR: Login failed. Account not validated.":
        vxConfirmation("error", "Need RapidPro", "A RapidPro account is required for High-Speed-Downloads.<br />Do you want to upgrade to RapidPro?", function(){
             self.vxShowBuyLogin();
        });
        return;
        break;
      case "IP address modified.":
      case "Please stop flooding our download servers.":
      case "Download auth invalid.":
      case "Download session expired.":
      case "Download session invalid.":
      case "Download session modified.":
      case "Download ticket not ready.":
      case "download: session invalid":
        vxConfirmation("error", "Download can not be started.", szxTranslate("The server returned with error <b>###error###</b>. <br />This is usually a temporary problem and can be solved by retrying the same URL at a later time or by becoming a <b>RapidPro</b>-user. <br />Do you want to upgrade to RapidPro?",{"error": err}), function(){
          RSPage["package"] = 1;
          load("overlay_downloadbuy.tpl", "", function(obj) {
            vxResizeOverlay(function() {
              $("js_overlay-box-content").innerHTML = trim(obj.responseText);
              RSPage["CPayment"].initPage();
            });
          });
        });
        return;
        break;
      case "This file is too big to download it for free.":
        if(!szError) szError = "The file size exceeds the volume of free use.<br /><b>Want to activate RapidPro?</b>";
        // Lösung: Auf Fehler hinweisen mit Option Premiumkunde zu werden.
        vxConfirmation("error", "RapidPro required!", szError, function(){
          self.vxShowBuyLogin();
        });
        return;
        break;
      //  Premuser-Download ohne RapidPro
      case "RapidPro expired.":
        // Lösung: Hinweis anzeigen und entweder Kaufen anbieten oder Aktivierung (wenn möglich)
        var cb = null;
        var err= "RapidPro has expired.<br /><b>Buy now Rapids to extend RapidPro?</b>";
        //  RapidPro-Aktivierung möglich?
        if(system["user"]["settingsloaded"] && system["user"]["settings"]["rapids"] >=100) {
          err = "RapidPro is required to download - you still have enough Rapids to activate RapidPro now.<br /><b>Want to activate RapidPro now?</b>";
          cb = function() {
              apicall(system["apiurl"]+"extendrapidpro_v1", function(obj) {
                  if (!checkResponse(obj.responseText,true)) {
                      vxResizeOverlay(function() {
                          $("js_confirmerror").innerHTML = obj.responseText;
                          $("js_confirmerror").style.display="";
                      });
                      return false;
                  }
                  vxCloseOverlay();
                  vxGetAccountDetails("&cookie="+system["user"]["settings"]["cookie"]);
                  showinfo("RapidPro was extended.");
              });
          };
        } else {
          var err= "You need an account to use the fast download option!<br /><b>Create an account now?</b>"; //REMX andere fehlermeldung werfen -> nutzer werden
          cb = function(){
            self.vxShowBuyLogin();
          }
        }
        vxConfirmation("error", "RapidPro required!", err, cb, null, '<div class="error" style="display:none;" id="js_confirmerror"></div>');
        return;
        break;
      //  RapidPro-Download ohne Traffic
      case "No traffic left.":
        // Lösung: Hinweis anzeigen und entweder Kaufen anbieten oder Aktivierung (wenn möglich)
        var cb = null;
        var err= "You don't have enough traffic to download this file.<br /><b>Want to buy more traffic?</b>";
        //  Traffic-Kauf möglich?
        if(system["user"]["settingsloaded"] && system["user"]["settings"]["rapids"] >= system["trafficPricing"]["min"]*system["trafficPricing"]["gbprice"] ) {
          cb = function() {
              load("overlay_premzone_buytraffic.tpl", "", function(obj) {
            var szOptions = '';
            for (var i=system["trafficPricing"]["min"];i<=system["trafficPricing"]["max"];i+=system["trafficPricing"]["step"])
                szOptions += '<option value="'+i+'">'+i+' GB / '+Math.ceil(i*system["trafficPricing"]["gbprice"])+' Rapids</option>';
                vxResizeOverlay(szxTranslate(obj.responseText,{"warning": "", "display": "block", "callback": null, "rapids": system["user"]["settings"]["rapids"], "options":szOptions}));
              });
          };
        } else {
          cb = function(){
            self.vxShowBuyLogin();
          }
        }
        vxConfirmation("error", "No traffic left", err, cb, null, '<div class="error" style="display:none;" id="js_confirmerror"></div>');
        return;
        break;
      case "You need RapidPro to download more files from your IP address.":
      case "All free download slots are full. Please try again later.":
        vxConfirmation("error", "Download can not be started.", szxTranslate("Too many parallel downloads form your IP address or the limit for free downloads has been reached. <br />This is usually a temporary problem and can be solved by retrying the same URL at a later time or by becoming a <b>RapidPro</b>-user. <br />Do you want to upgrade to RapidPro?",{"error": err}), function(){
          RSPage["package"] = 1;
          load("overlay_downloadbuy.tpl", "", function(obj) {
            vxResizeOverlay(function() {
              $("js_overlay-box-content").innerHTML = trim(obj.responseText);
              RSPage["CPayment"].initPage();
            });
          });
        });
        return;
        break;
      case "SSL downloads are only available for RapidPro customers.":  //  REMX: Die Meldung kommt wenn freeuser auf premdl klickt.
        vxConfirmation("error", "Download can not be started.", szxTranslate("Only RapidPro users can initiate encrypted downloads. <br />Do you want to upgrade to RapidPro?",{"error": err}), function(){
          RSPage["package"] = 1;
          load("overlay_downloadbuy.tpl", "", function(obj) {
            vxResizeOverlay(function() {
              $("js_overlay-box-content").innerHTML = trim(obj.responseText);
              RSPage["CPayment"].initPage();
            });
          });
        });
        return;
        break;
    }

    / *
    **  Nicht durch Geld lösbare Probleme
    * /
    //"You need to wait 852 seconds until you can download another file without having RapidPro.":
    var reg = /You need to wait (\d+) seconds until you can download another file without having RapidPro./;
    if( reg.exec(err) ){
      var counter = RegExp.$1;
      self.freedlCounter = counter;
      $('downloadpage_wrapper').style.display="none";
      $('downloadpage_freedl_wrapper').style.display="none";
      $('downloadpage_wait4freedl_wrapper').style.display="block";

      $('sidebar-lounge').style.display="none";
      $('sidebar-gute-gruende').style.display="block";

      if (system["downloadtimer"]) clearInterval(system["downloadtimer"]);
      system["downloadtimer"] = setInterval("RSPage['CDownloadPage'].freedownloadwaiting()",1000);
      $('js_wait4freedl-timerbox').innerHTML = ( (self.freedlCounter-(self.freedlCounter%60)) / 60 )+":"+(( self.freedlCounter%60 ) <10? '0':'')+( self.freedlCounter%60 );

    } else {
      //  direkt die fehlerseite anzeigen:
      $("download-errorbox").style.display="";
      $("downloadpage_wait4freedl_wrapper").style.display="none";
      $("downloadpage_freedl_wrapper").style.display="none";
      $("downloadpage_wrapper").style.display="none";
      var params = system["params"];
      var dl_file_serverid = params[1];
      var dl_file_id       = params[2];
      var dl_file_name     = params[3];
      var dl_file_sizekb   = params[4];
      var dl_error         = err;

      var szURL = "http://rapidshare.com/files/"+dl_file_id+"/"+dl_file_name;
      $('url_headarea').innerHTML = szURL;
      $("jsurl_file-download-head2").innerHTML = szURL;
      $("jsurl_file-download-size2").innerHTML = dl_file_sizekb;

      //  Fehlerauswertung:
      var szError = "";
      var szRedirect="";
      switch(dl_error) {
        case "File not found.":
        case "File physically not found.":
          szError = "This file was not found on our server.";
          break;
        case "File deleted R1.":   // Deleted by uploader
        case "File deleted R2.":   // Deleted by RapidShare Administrators
          szError = "The file was deleted by the owner.";
          break;
        case "File deleted R3.":   // No download for a longer period. Inactivity-timeout exceeded
        case "File deleted R5.":   // No download for a longer period. Inactivity-timeout exceeded
          szError = "The file was deleted due to our inactivity-rule (no downloads).";
          break;
        case "File deleted R4.":   // Suspicion of service-abuse
        case "File deleted R8.":   // THIS FILE IS FORBIDDEN TO BE SHARED! Complaints received
          szError = "The file is suspected to be contrary to our terms and conditions and has been locked up for clarification.";
          break;
        case "This file is marked as illegal.":
        case "File deleted R10.":  // Illegal distribution of a game
        case "File deleted R11.":  // Illegal distribution of a movie
        case "File deleted R12.":  // Illegal distribution of music
        case "File deleted R13.":  // Illegal distribution of software
        case "File deleted R14.":  // Illegal distribution of an image
        case "File deleted R15.":  // Illegal distribution of literature
          szError = "The file has been removed from the server due of infringement of the copyright-laws.";
          szError = "The file has been removed from the server due of infringement of the copyright-laws.";
          alert("This file is copyrighted and may not be distributed without permission of the copyright holder. We will direct you to rapidtainment.com where you can check out entertainment products.");
          if(dl_error.match("R10"))       top.location = 'HTTP://rapidgames.com/?rsa=true';
          else if (dl_error.match("R11")) top.location = 'HTTP://rapidmovies.com/?rsa=true';
          else if (dl_error.match("R12")) top.location = 'HTTP://rapidmusic.com/?rsa=true';
          else top.location = 'HTTP://rapidgames.com/?rsa=true';
          break;
        case "raid error on server.":
        case "File incomplete.":
          szError = "File corrupted or incomplete.";
          break;
        case "Secure download link modified.":
        case "Secured link expired.":
        case "Secured link modified.":
          szError = "The file was requested using an invalid secure link.";
          break;
        default:
          szError = dl_error;
      }
      if(szError) {
          $("js_downloaderror").style.display="";
          $("js_downloaderror").innerHTML = szError;
      }
    }
  }
  self.freedownloadwaiting = function(){
    if(self.freedlCounter==0){
      clearInterval(system["downloadtimer"]);
          $('downloadpage_wrapper').style.display="block";
          $('downloadpage_freedl_wrapper').style.display="none";
          $('downloadpage_wait4freedl_wrapper').style.display="none";

          $('sidebar-lounge').style.display="none";
          $('sidebar-gute-gruende').style.display="block";

          RSPage['CDownloadPage'].startFreeDl();
    } else {
      self.freedlCounter--;
    }
    $('js_wait4freedl-timerbox').innerHTML = ( (self.freedlCounter-(self.freedlCounter%60)) / 60 )+":"+(( self.freedlCounter%60 ) <10? '0':'')+( self.freedlCounter%60 );
  }

  self.getFileURL = function()
  {
    return "http://rapidshare.com/files/"+self.vars["dl_file_id"]+"/"+self.vars["dl_file_name"]+"";
  }
  self.showFeaturelist = function(){
    load("overlay_features.tpl", "", function(obj) {
        vxResizeOverlay();
        vxOpenOverlay(obj.responseText);
    });
  }
  self.getRapidPro = function(){
    RSPage["package"] = 1;
    load("overlay_downloadbuy.tpl", "", function(obj) {
        $("js_overlay-box-content").innerHTML = trim(obj.responseText);
        RSPage["CPayment"].initPage();
        vxOpenOverlay();
    });
  }

  self.fl_getFlash = function(obj){
      if(obj.cmd == "clickButton")
      {
            RSPage['CDownloadPage'].getRapidPro();
      }
  }

  / *self.startDownloadAnimation = function(){
        alert("startDownloadAnimation");
        var fl_animation = (window["animation"]?window["animation"]:document.getElementById("animation"));
        //var fl_button = (window["button"]?window["button"]:document.getElementById("button"));
        fl_animation.callFlash({"cmd": "startAnimation", "value": ""});
        //fl_button.callFlash({"cmd": "startAnimation", "value": ""});
  }* /
}

RSPage["onload"]=function()
{
  RSPage["CDownloadPage"] = new CDownloadPage();
  RSPage["CDownloadPage"].init();

  if(ixGetFlashVersion()>9){
    $('js-noflash-btn').style.display="none";
    $('js-flash-btn').style.display="block";
    $('js-flash1').style.display="block";
    $('js-flash2').style.display="block";
  } else {
    $('js-noflash-btn').style.display="block";
    $('js-flash-btn').style.display="none";
    $('js-flash1').style.display="none";
    $('js-flash2').style.display="none";
  }


}
RSPage["update_settings"] = function()
{
  if (system["user"]["settingsloaded"] && system["user"]["settings"]["onlyssldls"]=="1" && $("js_ssldownload")) {
    $("js_ssldownload").setAttribute("disabled","disabled");
    $("js_ssldownload").checked="checked";
  }
  delete(RSPage["update_settings"]);
}

function getButtonText(){
  return ( $('js-noflash-btn') && $('js-noflash-btn').innerHTML )?$('js-noflash-btn').innerHTML:"";
}

//
              */

            QRegExp reFileInfo("^(?:.*)rapidshare.com/files/([\\d]*)/(.*)$");

            if(this->http.lastResponse().hasKey("Location"))
            {
                this->_url = QUrl(this->http.lastResponse().value("Location"));
            }

            if(reFileInfo.indexIn(this->_url.toString()) != -1)
            {
                this->apiFileId = reFileInfo.cap(1).toULong();
                this->apiFilename = reFileInfo.cap(2);

                cookie = "";
                QUrl url("http://api.rapidshare.com/cgi-bin/rsapi.cgi");
                QByteArray post = "sub=download_v1&fileid=" + QUrl::toPercentEncoding(QString("%1").arg(this->apiFileId)) + "&filename=" + QUrl::toPercentEncoding(this->apiFilename);
                step = 1;
                waitingId = request(url, "POST", post, QMap<QString, QString>());
            } else
            {
                this->_errorStr = tr("Unknown error !!");
                setError();
                return;
            }

            break;
        }

        case 1:
        {
            if(!checkRsResponse())
            {
                setError();
                return;
            }

            break;
        }

        case 2:
        {
            this->_downloadFile->close();
            speedTimer.stop();
            this->_downloadEnd = QDateTime::currentDateTime();

            if(this->_downloadFile->exists())
            {
                if(this->_downloadFile->size() < 20480)
                {
                    if(this->_downloadFile->open(QIODevice::ReadOnly | QIODevice::Text))
                    {
                        QString tmpStr = this->_downloadFile->readAll();
                        this->_downloadFile->close();

                        QRegExp re("<p>Your IP address (?:[\\.|\\d]*) is already downloading a file.  Please wait until the download is completed.</p>");
                        QRegExp re2("<p>The download session has expired. <a href=\"(?:[^\"]*)\">Please click here to start the download again.</a></p>");

                        if(re.indexIn(tmpStr) || re.indexIn(tmpStr))
                        {
                            this->_downloadFile->remove();
                            start();
                            return;
                        }
                    }
                }
            }

            this->_state = STATE_FINISHED;

            emit downloadFinished(this->_id, false);
            break;
        }
    }

/*
    switch(step)
    {
        default:
        case 0:
        {
            if(this->http.lastResponse().hasKey("Location"))
            {
                this->_url = QUrl(this->http.lastResponse().value("Location"));
                qDebug() << "found Location" << this->_url;

                waitingId = request(this->_url, "GET", QByteArray(), QMap<QString, QString>());
                return;
            }

            QUrl tmpUrl;

            if(page.indexOf(QRegExp("<!-- E#4 -->")) != -1)
            {
                this->_errorStr = tr("The file could not be found. Please check the download link.");
                setError();
                return;
            } else
            {
                QRegExp re("<form action=\"([^\"]*)\" method");
                QRegExp re2("<script(?:[^>]*)>location=\"([^\"]*)\";</script>");

                if(re.indexIn(page) != -1)
                {
                    tmpUrl = QUrl(re.cap(1));

                    QRegExp re2(">\\| (\\d+) (.)B</font></p>");
                    if(re2.indexIn(page) != -1)
                    {
                        quint64 tmpSize = re2.cap(1).toUInt();

                        QStringList sizeNames = QStringList() << " " << "K" << "M" << "G" << "T" << "P";

                        for(int i=0; i<sizeNames.count(); ++i)
                        {
                            if(re2.cap(2) == sizeNames.at(i))
                            {
                                double tmpDbl = tmpSize;

                                for(int o=0; o<i; ++o)
                                    tmpDbl = tmpDbl * multipl;

                                this->_fileSize = tmpDbl;
                            }
                        }

                    } else
                    {
                        this->_fileSize = 100*multipl*multipl;
                    }
                } else if(re2.indexIn(page) != -1)
                {
                    QStringList strList = re2.cap(1).split("|");
                    this->_fileSize = strList.at(4).toUInt()*multipl;
                    tmpUrl = QUrl("rapidshare.com" + re2.cap(1));
                } else
                {
                    this->_errorStr = tr("Unknown error !!");
                    setError();
                }

                qDebug() << tmpUrl;
                return;

                step = 1;

                QByteArray post = "";
                post.append("dl.start=Free");

                QString tmpStr = tmpUrl.path();
                int pos = tmpStr.lastIndexOf("/") + 1;
                this->_file = tmpStr.mid(pos);
                qDebug() << "emit changeName" << this->_file;
                emit changeName(this->_id, this->_file);

                waitingId = request(tmpUrl, "POST", post, QMap<QString, QString>());
            }

            break;
        }

        case 1:
        {
            QRegExp reSmallWait("var c=([^;]*);");
            QRegExp reBlockWait("Or try again in about (\\d*) minutes");
            QRegExp reSlotBlocked("<p>Your IP address ([\\.|\\d]*) is already downloading a file.  Please wait until the download is completed.</p>");
            QRegExp reSessionExpired("<p>The download session has expired. <a href=\"([^\"]*)\">Please click here to start the download again.</a></p>");
            QRegExp reServerFull("<b>Currently a lot of users are downloading files.  Please try again in (\\d*) minutes");
            QRegExp reNoSlots("We regret that currently we have no available slots for free users. Unfortunately you will have to wait (\\d*) minutes, this will allow us to continue to provide our service to our Premium users\\.");
            QRegExp reOverloaded("<p align=\"justify\">Unfortunately right now our servers are overloaded and we have no more download slots left for non-members. Of course you can also try again later.</p>");

            QRegExp reForm("<form action=\"([^\"]*)\" method");

            //todo:
            if(reSmallWait.indexIn(page) != -1)
            {
                int tmpTime = reSmallWait.cap(1).toInt();

                //<form name="dlf" action="http://rs138l34.rapidshare.com/files/347266214/9802029/raptor-0.17.tar.gz" method="post">
                //<input  type="radio" name="mirror" onclick="document.dlf.action=\'http://rs138l33.rapidshare.com/files/347266214/9802029/raptor-0.17.tar.gz\';" /> Level(3) #3<br />

                QStringList links;
                QRegExp reLink("<form name=\"dlf\" action=\"([^\"]*)\" method=\"post\">");
                if(reLink.indexIn(page) != -1)
                {
                    links.append(reLink.cap(1));
                }

                QRegExp reLinks("<input(?:[^>]*)onclick=\"document\\.dlf\\.action=\\\\'([^\\\\]*)\\\\';\" />([^<]*)<br />");
                int pos = 0;
                while((pos = reLinks.indexIn(page, pos)) != -1)
                {
                    links.append(reLinks.cap(1));
                    pos += reLinks.matchedLength();
                }

                this->_url = QUrl(selectMirror(links));

                if(this->_url.toString() == "")
                {
                    qDebug() << page;
                    this->_errorStr = tr("No download link found.");
                    setError();
                    return;
                }

                this->_state = STATE_WAITING;
                emit statusMsg(this->_logId, tr("Waiting %1 seconds.").arg(tmpTime));

                action = ACTION_DOWNLOAD;

                this->_timeLeft = tmpTime;
                wait = this->_timeLeft;

                waitTimer.start(1000);

            } else if(reBlockWait.indexIn(page) != -1)
            {
                int tmpTime = reBlockWait.cap(1).toInt();

                this->_timeLeft = tmpTime*60;
                wait = this->_timeLeft;

                action = ACTION_START;
                waitTimer.start(1000);

                this->_state = STATE_WAITING;
                emit statusMsg(this->_logId, tr("Try again in %1 minutes.").arg(tmpTime));

            } else if(reSlotBlocked.indexIn(page) != -1) //klappt
            {
                emit statusMsg(this->_logId, tr("IP (%1) is blocked.").arg(reSlotBlocked.cap(1)));

                this->_state = STATE_WAITING;

                this->_timeLeft = 60*5;
                wait = this->_timeLeft;

                action = ACTION_START;
                waitTimer.start(1000);

            } else if(reSessionExpired.indexIn(page) != -1)
            {
                emit statusMsg(this->_logId, tr("The download session has expired."));
                start();

            } else if(reServerFull.indexIn(page) != -1)
            {
                int tmpTime = reServerFull.cap(1).toInt();

                this->_state = STATE_WAITING;

                this->_timeLeft = tmpTime*60;
                wait = this->_timeLeft;

                action = ACTION_START;
                waitTimer.start(1000);

                emit statusMsg(this->_logId, tr("Currently a lot of users are downloading files. Please try again in %1 minutes").arg(tmpTime));
            } else if(reNoSlots.indexIn(page) != -1)
            {
                int tmpTime = reNoSlots.cap(1).toInt();

                emit statusMsg(this->_logId, tr("We regret that currently we have no available slots for free users. Unfortunately you will have to wait %1 minutes, this will allow us to continue to provide our service to our Premium users.").arg(tmpTime));
            } else if(reOverloaded.indexIn(page) != -1)
            {
                this->_state = STATE_WAITING;

                this->_timeLeft = 10;
                wait = this->_timeLeft;

                action = ACTION_START;
                waitTimer.start(1000);

                emit statusMsg(this->_logId, tr("Unfortunatly right now our servers are overloaded and we have no more download slots left for non-members. Of course you can also try again later."));
            } else
            {
                qDebug() << page;
                this->_errorStr = tr("Unknown error in step 1 !!");
                setError();
                return;
            }
            break;
        }

        case 2:
        {
            this->_downloadFile->close();
            speedTimer.stop();
            this->_downloadEnd = QDateTime::currentDateTime();

            if(this->_downloadFile->exists())
            {
                if(this->_downloadFile->size() < 20480)
                {
                    if(this->_downloadFile->open(QIODevice::ReadOnly | QIODevice::Text))
                    {
                        QString tmpStr = this->_downloadFile->readAll();
                        this->_downloadFile->close();

                        QRegExp re("<p>Your IP address (?:[\\.|\\d]*) is already downloading a file.  Please wait until the download is completed.</p>");
                        QRegExp re2("<p>The download session has expired. <a href=\"(?:[^\"]*)\">Please click here to start the download again.</a></p>");

                        if(re.indexIn(tmpStr) || re.indexIn(tmpStr))
                        {
                            this->_downloadFile->remove();
                            start();
                            return;
                        }
                    }
                }
            }

            this->_state = STATE_FINISHED;

            emit downloadFinished(this->_id, false);
            break;
        }
    }
    */
}

void pluginHoster::setSpeed(double const& newSpeed)
{
    if(!speedList.isEmpty() && speedList.count() == this->smooth)
    {
        speedList.removeFirst();
        speedList.append(newSpeed);
    } else
    {
        speedList.append(newSpeed);
    }

    double tmpDbl = 0;

    for(int i=0; i<speedList.size(); ++i)
    {
        tmpDbl += speedList.at(i);
    }

    if(speedList.isEmpty())
        this->_speed = 0;
    else
        this->_speed = (tmpDbl / speedList.size());

    if(this->_speed < 1) this->_speed = 0;
}

//<- private


//slots ->
void pluginHoster::slot_http_requestFinished(int id, bool error)
{
    if(abort || error)
    {
        if(this->_downloadFile->isOpen()) this->_downloadFile->close();
        this->_errorStr = http.errorString();
        //emit deleteMe(this->_id, error);
        setError();
        return;
    }

    if(waitingId != id) return;
    page = QString(response);

    switch(this->_mode)
    {
        case MODE_FREE:
            doFree();
            break;

        case MODE_PREMIUM:
            doPremium();
            break;

        case MODE_GET_SIZE:
            doGetSize();
            break;

        case MODE_LOGIN:
            doLogin();
            break;
    }
}

void pluginHoster::slot_http_readyRead(const QHttpResponseHeader & resp)
{
    Q_UNUSED(resp);
    response.append(this->http.readAll());
}

void pluginHoster::slot_http_dataReadProgress(int done, int total)
{
    if(this->_state == STATE_DOWNLOADING)
    {
        this->_downloaded = done;
        this->_fileSize = total;
        //qDebug() << "slot_http_dataReadProgress" << this->_fileSize;

        if(this->_fileSize > 0) this->_progress = (int)((double)this->_downloaded * 100.0 / (double)this->_fileSize);
    }
}

void pluginHoster::slot_http_sslErrors(const QList<QSslError> & errors)
{
    //todo:
    Q_UNUSED(errors);
    this->http.ignoreSslErrors();
}

void pluginHoster::slot_speedTimer_timeout()
{
    if(speedTimer.interval() > 0) setSpeed((this->_downloaded - lastSize) / ((double)speedTimer.interval() / 1000.0));

    lastSize = this->_downloaded;

    if(this->_speed > 0) this->_timeLeft = (int)((double)(this->_fileSize - this->_downloaded) / this->_speed);
}

void pluginHoster::slot_waitTimer_timeout()
{
    if(this->_state == STATE_STOPPED) return;

    --this->_timeLeft;

    if(wait > 0) this->_progress = (int)(100 * ((double)(wait - this->_timeLeft) / wait));

    if(this->_timeLeft <= 0)
    {
        waitTimer.stop();

        switch(action)
        {
            case ACTION_NONE:

                break;

            case ACTION_START:

                start();
                break;

            case ACTION_API:
            {
                if(!this->_downloadDir.exists(this->_folder)) this->_downloadDir.mkdir(this->_folder);

                this->_downloadDir.cd(this->_folder);

                while(this->_downloadDir.exists(this->_file))
                {
                    emit statusMsg(this->_logId, tr("file exists, renaming."));
                    this->_file = "_" + this->_file;
                }

                this->_downloadFile = new QFile(this->_downloadDir.filePath(this->_file));
                if(!this->_downloadFile->open(QIODevice::WriteOnly))
                {
                    this->_errorStr = this->_downloadFile->errorString();//tr("Cant open file.");
                    setError();
                    return;
                }

                step = 2;

                this->_state = STATE_DOWNLOADING;

                emit statusMsg(this->_logId, tr("Starting download."));

                this->_progress = 0;
                this->_downloadStart = QDateTime::currentDateTime();
                this->_downloadEnd = this->_downloadStart;
                this->_downloadEnd.addSecs(-1);

                cookie = "";
                QUrl url("http://" + this->apiHostname + "/cgi-bin/rsapi.cgi");
                QByteArray post = "sub=download_v1&fileid=" + QUrl::toPercentEncoding(QString("%1").arg(this->apiFileId)) + "&filename=" + QUrl::toPercentEncoding(this->apiFilename) + "&dlauth=" + QUrl::toPercentEncoding(this->apiAuth);

                waitingId = request(url, "POST", post, QMap<QString, QString>(), this->_downloadFile);

                break;
            }

            case ACTION_DOWNLOAD:
            {
                if(!this->_downloadDir.exists(this->_folder)) this->_downloadDir.mkdir(this->_folder);

                this->_downloadDir.cd(this->_folder);

                while(this->_downloadDir.exists(this->_file))
                {
                    emit statusMsg(this->_logId, tr("file exists, renaming."));
                    this->_file = "_" + this->_file;
                }

                this->_downloadFile = new QFile(this->_downloadDir.filePath(this->_file));
                if(!this->_downloadFile->open(QIODevice::WriteOnly))
                {
                    this->_errorStr = this->_downloadFile->errorString();//tr("Cant open file.");
                    setError();
                    return;
                }

                step = 2;
                this->_state = STATE_DOWNLOADING;

                emit statusMsg(this->_logId, tr("Starting download."));


                this->_progress = 0;
                this->_downloadStart = QDateTime::currentDateTime();
                this->_downloadEnd = this->_downloadStart;
                this->_downloadEnd.addSecs(-1);

                QByteArray post = "mirror=on";

                waitingId = request(this->_url, "POST", post, QMap<QString, QString>(), this->_downloadFile);
                break;
            }
        }
    }
}

void pluginHoster::slot_applyButton_clicked()
{
    QSettings settings("raptor-loader", "Raptor");

    settings.setValue("hoster/" + this->_info.name + "/maxDownloads", maxDownloadsSpinBox->value());
}

void pluginHoster::slot_authLoginButton_clicked()
{
    connect(this, SIGNAL(loginFinished(const int, const bool)), this, SLOT(slot_raptor_hosterLoginFinished(const int, const bool)));

    login(authUser->text(), authPass->text());
}

void pluginHoster::slot_authDeleteButton_clicked()
{
    QSettings settings("raptor-loader", "Raptor");

    settings.beginGroup("hoster/" + this->info().name + "/settings");
    settings.remove("");
    settings.endGroup();

    emit changeMode(0, MODE_FREE);
}

void pluginHoster::slot_raptor_hosterLoginFinished(int const& id, bool const& error)
{
    Q_UNUSED(id);

    disconnect(this, SIGNAL(loginFinished(const int, const bool)), this, SLOT(slot_raptor_hosterLoginFinished(const int, const bool)));

    if(error)
    {
        emit messageBox(tr("Login"), tr("Login failed. %1").arg(this->_errorStr));

        slot_authDeleteButton_clicked();
    } else
    {
        emit messageBox(tr("Login"), tr("Login was successful."));
    }
}

//<- slots

Q_EXPORT_PLUGIN2(rapidshare_com, pluginHoster);
